跳到主要内容

GPIO 使用

1. GPIO简介

GPIO,全称 General-Purpose Input/Output(通用输入输出),是一种在计算机和嵌入式系统中常见的数字输入输出接口。它允许软件控制硬件的数字输入和输出,例如开关、传感器、LED灯等。GPIO通常由一个芯片或处理器上的引脚提供支持,通过编程可以配置这些引脚为输入或输出,并且可以通过相应的软件命令来读取输入状态或控制输出状态。

2. GPIO引脚编号计算方法

RK3588共 有 5 组 GPIO bank:GPIO0~GPIO4,每组又以 A0~A7, B0~B7, C0~C7, D0~D7 作为编号区分,常用以下公式计算引脚:

 GPIO pin脚计算公式:pin = bank * 32 + number

GPIO 小组编号计算公式:number = group * 8 + X

例如: GPIO3_B5的计算方式 : 32 3 + 1 8 + 5 = 109 ---> 也就是说,GPIO3_B5对应的是GPIO的编号是gpio-109。

3. 复用

GPIO口除了通用输入输出功能外,还可能有其它复用功能

rockchip-gpio

从原理图中看出:以GPIO1_C0为例,就有如下几个功能:

func0func1func2func3
GPIO1_C0I2C3_SDA_M0UART3_RX_M0SPI4_MISO_M0

在系统DTS配置中GPIO1_C0默认是I2C3_SDA_M0功能。如果我们想将GPIO1_C0复用为UART3_RX_M0功能,该怎么做呢?

  1. 首先打开uart3 节点,将pinctrl配置为uart3m0_xfer。pinctrl配置是GPIO复用的最关键的配置,在这里就是将GPIO1_C0复用做了uart3功能。
&uart3 {
pinctrl-names = "default";
pinctrl-0 = <&uart3m0_xfer>;
status = "okay";
};

&pinctrl {
uart3 {
/omit-if-no-ref/
uart3m0_xfer: uart3m0-xfer {
rockchip,pins =
/* uart3_rx_m0 */
<1 RK_PC0 10 &pcfg_pull_up>, # 将GPIO1_C0复用为uart3_rx_m0
/* uart3_tx_m0 */
<1 RK_PC1 10 &pcfg_pull_up>; # 将GPIO1_C1复用为uart3_tx_m0
};
};
};

  1. 如果发现GPIO1_C0被复用为I2c3,则在dts中关闭它。
&i2c3 {
status = "disabled";
};

这样,我们就将GPIO1_C0复用为了UART3_RX_M0功能

4. GPIO调试方法

4.1 读取GPIO状态信息

Debugfs 文件系统目的是为开发人员提供更多内核数据,方便调试。 这里 GPIO 的调试也可以用 Debugfs 文件系统,获得更多的内核信息。GPIO 在 Debugfs 文件系统中的接口为 /sys/kernel/debug/gpio,可以这样读取该接口的信息:

armsom@armsom:~$ sudo cat /sys/kernel/debug/gpio
gpiochip0: GPIOs 0-31, parent: platform/fd8a0000.gpio, gpio0:
gpio-15 ( |led_rgb_b ) out lo
gpio-20 ( |reset ) out lo ACTIVE LOW
gpio-21 ( |bt_default_wake_host) in hi

gpiochip1: GPIOs 32-63, parent: platform/fec20000.gpio, gpio1:
gpio-34 ( |bt_default_rts ) in hi
gpio-36 ( |vcc3v3-pcie30 ) out lo
gpio-40 ( |camera-pwdn-gpio ) out hi
gpio-54 ( |hdmirx-det ) in lo ACTIVE LOW
gpio-58 ( |vcc3v3-pcie2x1l0 ) out hi
gpio-61 ( |headset_gpio ) in hi

gpiochip2: GPIOs 64-95, parent: platform/fec30000.gpio, gpio2:
gpio-78 ( |vbus5v0-typec ) out lo

gpiochip3: GPIOs 96-127, parent: platform/fec40000.gpio, gpio3:
gpio-101 ( |vcc-5v0-gpio-regulat) out hi
gpio-102 ( |bt_default_reset ) out lo
gpio-104 ( |reset ) out hi
gpio-125 ( |bt-wake-gpio-regulat) out hi

gpiochip4: GPIOs 128-159, parent: platform/fec50000.gpio, gpio4:
gpio-130 ( |wifi-diable-gpio-reg) out hi
gpio-134 ( |sbu1-dc ) out lo
gpio-135 ( |sbu2-dc ) out lo
gpio-136 ( |vcc5v0-host-regulato) out hi
gpio-149 ( |led_rgb_r ) out lo

gpiochip5: GPIOs 509-511, parent: platform/rk806-pinctrl.9.auto, rk806-gpio, can sleep:

从读取到的信息中可以知道,内核把 GPIO 当前的状态都列出来了,以 GPIO0组为例,gpio-15(GPIO0_B7) 对应的dts节点是led_rgb_b,输出低电平 (out lo)。

4.2 查看 pinmux-pins

armsom@armsom:~$ sudo cat /sys/kernel/debug/pinctrl/pinctrl-rockchip-pinctrl/pinmux-pins
Pinmux settings per pin
Format: pin (name): mux_owner gpio_owner hog?
pin 0 (gpio0-0): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 1 (gpio0-1): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 2 (gpio0-2): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 3 (gpio0-3): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 4 (gpio0-4): fe2c0000.mmc (GPIO UNCLAIMED) function sdmmc group sdmmc-det
pin 5 (gpio0-5): feb20000.spi (GPIO UNCLAIMED) function spi2 group spi2m2-pins
pin 6 (gpio0-6): feb20000.spi (GPIO UNCLAIMED) function spi2 group spi2m2-pins
pin 7 (gpio0-7): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 8 (gpio0-8): 6-0051 (GPIO UNCLAIMED) function hym8563 group rtc-int
pin 9 (gpio0-9): feb20000.spi (GPIO UNCLAIMED) function spi2 group spi2m2-cs0
pin 10 (gpio0-10): wireless-wlan (GPIO UNCLAIMED) function wireless-wlan group wifi-host-wake-irq
pin 11 (gpio0-11): feb20000.spi (GPIO UNCLAIMED) function spi2 group spi2m2-pins
pin 12 (gpio0-12): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 13 (gpio0-13): fiq-debugger (GPIO UNCLAIMED) function uart2 group uart2m0-xfer
pin 14 (gpio0-14): fiq-debugger (GPIO UNCLAIMED) function uart2 group uart2m0-xfer
pin 15 (gpio0-15): leds gpio0:15 function leds group led-rgb-b
pin 16 (gpio0-16): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 17 (gpio0-17): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 18 (gpio0-18): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 19 (gpio0-19): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 20 (gpio0-20): sdio-pwrseq gpio0:20 function sdio-pwrseq group wifi-enable-h
pin 21 (gpio0-21): (MUX UNCLAIMED) gpio0:21
...

我们以pin 13 (gpio0-13): fiq-debugger (GPIO UNCLAIMED) function uart2 group uart2m0-xfer作为解析:

gpio0-13对应的节点名是 fiq-debugger,此节点使用pinctrl配置复用为debug串口功能,pinctrl的值是uart2m0-xfer。

5. GPIO控制

5.1 GPIO系统接口

基于sysfs的用户空间GPIO控制: sysfs控制gpio的方式主要是基于内核提供的gpio控制接口文件。也就是通过读写/sys/class/gpio目录下的文件来控制对应的gpio接口。

echo 109 > /sys/class/gpio/export                  # 申请导出相应的gpio
echo out > /sys/class/gpio/gpio109/direction # 设置相应gpio为输出方向
echo 1 > /sys/class/gpio/gpio109/value # 设置输出高电平
cat /sys/class/gpio/gpio109/value # 获取gpio当前状态值,是高电平还是低电平
echo 109 > /sys/class/gpio/unexport # 释放申请的gpio

注意:只有当GPIO3_B5脚没有被其它外设复用时, 我们才可以通过export导出该引脚去使用

5.2 GPIOD使用

libgpiod是一种字符设备接口,GPIO访问控制是通过操作字符设备文件(比如 /dev/gpiodchip0 )实现的, 并通过libgpiod提供一些命令工具、c库以及python封装。

使用libgpiod之前需要在板卡上安装libgpiod库:

#安装gpiod命令行工具
sudo apt install gpiod

gpiod工具的使用方法与sysfs接口的不同,gpiod是以控制器为单位,然后再详细到端口号和索引号,即gpiod使用两个数据确定引脚

引脚控制器端口号索引号gpiod的使用结果
GPIO3_C13C13 17(2x8+1)
GPIO3_B73B73 15(1X8+7)
GPIO1_B21B21 10(1x8+1)

以GPO3_C3为例,常用的命令行如下:

gpiodetct#列出所有GPIO控制器
gpioinfo 3#列出第一组控制器引脚组
gpioset 3 19=0#将第一组控制器编号的引脚3设置为低电平
gpioget 3 19#获取第一组中3号控制器的引脚状态
gpiomon 3 19#监控第一组中3号控制器的引脚状态

Rockchip Pin的ID按照 控制器(bank)+端口(port)+索引序号(pin) 组成,其中端口号和索引号会合并成一个数值传入到gpiod里去,并不是所有的引脚都能够使用libgpiod控制,例如led之类的一些已经被使用的引脚。